/**************************************************************************************
*
*	Copyright (C) 2009 - 2012 Brent Andrew O. Chua - See LICENSE.txt for more info.
*		
*	Filename	-	ComponentBillboard.cpp
*
*	Comments	-	See ComponentBillboard.h
*
**************************************************************************************/

#include "../Include/ComponentBillboard.h"
#include "../Include/Scene.h"
#include "../Include/Actor.h"

#include "../Include/EventNewActiveCamera.h"

namespace Pulse
{
	ComponentBillboard::ComponentBillboard( Actor *pOwner )
		: IComponent( pOwner )
	{

	}

	ComponentBillboard::~ComponentBillboard( void )
	{
		// Remove scene event listener
		GetOwnerUnsafe()->GetScene()->RemoveListener( EEvent::SCENE_NEW_ACTIVE_CAMERA, this, &ComponentBillboard::OnSceneNewActiveCamera );

	}

	EErrorCode::Type ComponentBillboard::Initialize( XMLElementPtr pElem )
	{
		ActorPtr pActorCam = GetOwnerUnsafe()->GetScene()->GetCamera();
		
		m_pActorCam = pActorCam;
		m_pCamera = (ComponentCamera*)pActorCam->GetComponent( EComponent::CAMERA );

		// Register scene event listener
		GetOwnerUnsafe()->GetScene()->AddListener( EEvent::SCENE_NEW_ACTIVE_CAMERA, this, &ComponentBillboard::OnSceneNewActiveCamera );

		return EErrorCode::OKAY;
	}

	EErrorCode::Type ComponentBillboard::PostInitialize( void )
	{

		return EErrorCode::OKAY;
	}

	void ComponentBillboard::Update( FLOAT dt )
	{
		if ( ActorPtr pActorCam = m_pActorCam.Lock() )
		{

			const Matrix4x4 *pCamTransform = pActorCam->GetTransformWorld();
			const Vector3 camPos = pCamTransform->GetTranslation();
			Matrix4x4 newTransform;

			// Assume that world up is 0, 1, 0
			// Set the transform to look at the target
			const Vector3 worldUp( 0.0f, 1.0f, 0.0f );	// TODO: Move this somewhere as a global setting...
			Actor *pActor = GetOwnerUnsafe();

			newTransform.BuildLookAt( pActor->GetTransformWorld()->GetTranslation(),
				camPos, worldUp );

			pActor->SetTransformWorld( &newTransform );
		}

	}

	void ComponentBillboard::OnSceneNewActiveCamera( IEvent *pEvent )
	{
		EventNewActiveCamera *pNewCamEvent = (EventNewActiveCamera*)pEvent;

		m_pActorCam = pNewCamEvent->GetNewActorCamera();

		if ( ActorPtr pActorCam = m_pActorCam.Lock() )
		{
			m_pCamera = (ComponentCamera*)pActorCam->GetComponent( EComponent::CAMERA );
		}
	}

}